﻿using System;
using System.Collections.Generic;
using System.Net;
using System.IO;
using System.Text.RegularExpressions;
using WebSupergoo.ABCpdf8;

namespace Stackoverflow_Reader
{
    internal class Parser
    {
        private bool sort;
        private bool intitle;
        private int numQuestions;
        private string keyword;
        private bool _isContinue = true;

        public bool isContinue
        {
            get { return _isContinue; }
            set { _isContinue = value; }
        }

        public event EventHandler QuestionParsed;

        public Parser(bool sorting, int questions, string keyword, bool title)
        {
            sort = sorting;
            numQuestions = questions;
            this.keyword = keyword;
            intitle = title;
        }

        public List<question> GetLinks()
        {
            List<question> questions = new List<question>();
            HttpWebRequest request;
            string content;
            int pagesNum = 0;
            string sortquery = null;

            HttpWebResponse response;
            try
            {
                /*if (sort)
                    sortquery = "http://stackoverflow.com/search?q=" + keyword + "&tab=votes&pagesize=50&page=";
                else
                    sortquery = "http://stackoverflow.com/search?q=" + keyword + "&tab=newest&pagesize=50&page=";*/

                //http://stackoverflow.com/search/?tab=votes&q=%2btitle%3ahtml4&pagesize=50&page=1
                if (intitle)
                    sortquery = "http://stackoverflow.com/search/?tab=votes&q=%2btitle%3a" + keyword +
                                "&pagesize=50&page=";
                else
                    sortquery = "http://stackoverflow.com/search/?tab=votes&q=" + keyword + "&pagesize=50&page=";

                request = HttpWebRequest.Create(sortquery + "1") as HttpWebRequest;
                request.UserAgent = @"Mozila/4.0 (compatible; MSIE 6.0;Windows NT 5.1; SV1; MyIE2;";
                request.Accept =
                    @"image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash,application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*";
                request.Headers.Add("Accept-Language", "en-us");

                response = request.GetResponse() as HttpWebResponse;

                StreamReader sr1 = new StreamReader(response.GetResponseStream());
                content = sr1.ReadToEnd();
                string sCookies =
                    String.IsNullOrEmpty(response.Headers["Set-Cookie"]) ? "" : response.Headers["Set-Cookie"];


                //Regex regEx = new Regex(@"<a href=""\S+"" title=""go to page \d+""><span class=""page-numbers"">(\d+)</span></a>\s+?<a href=""\S+"" title=""go to page \d+""><span class=""page-numbers next"">", 0);
                Regex regEx =
                    new Regex(
                        @"<a href=""\S+"" title=""go to page \d+""><span class=""page-numbers"">(\d+)</span></a>\s+?<a href=""\S+"" title=""go to page \d+"" rel=""next""><span class=""page-numbers next"">",
                        0);
                Match match = regEx.Match(content);
                if (match.Groups[1].Value != "")
                    pagesNum = Convert.ToInt32(match.Groups[1].Value);
                Regex regEx1 = new Regex(@"<a href=""(\S+)"" title=""questions with the most votes"">votes</a>", 0);
                Match match1 = regEx1.Match(content);
                if (match1.Success)
                {
                    if (sort)
                        sortquery = "http://stackoverflow.com/questions/tagged?tagnames=" + keyword +
                                    "&sort=votes&pagesize=50";
                    else
                        sortquery = "http://stackoverflow.com/questions/tagged?tagnames=" + keyword +
                                    "&sort=newest&pagesize=50";
                }
                for (int i = 1; i <= pagesNum && questions.Count != numQuestions; i++)
                {
                    request = HttpWebRequest.Create(sortquery + i.ToString()) as HttpWebRequest;

                    request.Headers.Add(HttpRequestHeader.Cookie, sCookies);
                    request.UserAgent = @"Mozila/4.0 (compatible; MSIE 6.0;Windows NT 5.1; SV1; MyIE2;";
                    request.Accept =
                        @"image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash,application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*";
                    request.Headers.Add("Accept-Language", "en-us");
                    response = request.GetResponse() as HttpWebResponse;
                    StreamReader sr = new StreamReader(response.GetResponseStream());
                    Regex reg =
                        new Regex(
                            @"<div class=""question-summary"" id=""question-summary\S*\d*"">\s+?<div class=""statscontainer"">\s+?<div class=""statsarrow""></div>\s+?<div class=""stats"">\s+?<div class=""vote"">\s+?<div class=""votes"">\s+?<span class=""vote-count-post""><strong>[<span style=""\S+"">]*(\d+)[</span>]*</strong></span>\s+? <div class=""viewcount"">vote[s]?</div>\s+?</div>\s+?</div>\s+?<div class=""status \S+"">\s+?<strong>\d+</strong>answer[s]?\s+?</div>\s+?</div>\s+?<div class=""[^>.]+>[^>.]+>\s+?</div>\s+?<div class=""summary"">\s+?<h3><a href=""(\S+)""\sclass=""question-hyperlink"">",
                            0);
                    content = sr.ReadToEnd();
                    MatchCollection maches = reg.Matches(content);
                    foreach (Match m in maches)
                    {
                        questions.Add(new question(Convert.ToInt32(m.Groups[1].Value),
                                                   "http://stackoverflow.com" + m.Groups[2].Value));
                        if (questions.Count == numQuestions)
                        {
                            break;
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                throw
                    new Exception(ex.Message);
            }

            return questions;
        }


        public Doc GetQuestions(List<question> links)
        {
            // step 1: creation of a document-object

            Doc theDoc = new Doc();
            Regex regEx =
                new Regex(
                    @"<a href=""\S+"" title=""go to page \d+""><span class=""page-numbers"">(\d+)</span></a>\s+?<a href=""\S+"" title=""go to page \d+""><span class=""page-numbers next"">",
                    0);
            Match match = null;
            HttpWebRequest reqest;
            HttpWebResponse response;
            string content;
            string currentLink;
            StreamReader sr = null;
            
            Doc theDocTemp = new Doc();
            int pageNum = 1;
            Regex regExLink = new Regex(@"http://stackoverflow.com/questions/\d+/", 0);
            Match matchLink = null;
            FileStream fsErrorLog = new FileStream("ErrorLog.txt", FileMode.OpenOrCreate);
            StreamWriter sw = new StreamWriter(fsErrorLog);

            //for now just do one page of answers

            for (int i = 0; i < links.Count; i++)
            {
                try
                {
                    reqest = HttpWebRequest.Create(links[i].link) as HttpWebRequest;
                    matchLink = regExLink.Match(links[i].link);

                    response = reqest.GetResponse() as HttpWebResponse;
                    sr = new StreamReader(response.GetResponseStream());
                    content = sr.ReadToEnd();
                    match = regEx.Match(content);
                    if (match.Success)
                        pageNum = Convert.ToInt32(match.Groups[1].Value);

                    for (int j = 1; j <= pageNum; j++)
                    {
                        try
                        {
                            theDocTemp.Rect.Inset(10, 10);
                            currentLink = matchLink.Value + "?sort=votes&page=" + j.ToString();
                            theDocTemp.Page = theDocTemp.AddPage();

                            int theID1;


                            theID1 = theDocTemp.AddImageUrl(currentLink);
                            
                            while (true)
                            {
                                theDoc.FrameRect(5, 5);

                                if (!theDocTemp.Chainable(theID1))
                                    break;

                                theDocTemp.Page = theDocTemp.AddPage();
                                theID1 = theDocTemp.AddImageToChain(theID1);
                            }

                            for (int k = 1; k <= theDocTemp.PageCount; k++)
                            {
                                theDocTemp.PageNumber = k;
                                theDocTemp.Flatten();
                            }

                            theDoc.Append(theDocTemp);

                            theDocTemp.Clear();
                        }
                        catch (Exception ex)
                        {
                            sw.Write("\r\n[" + DateTime.Now.ToString() + "] " + ex.Message + " Keyword: " + keyword +
                                     " Questoin: " + i.ToString() + " Page: " + j.ToString() + "\n\n\n");
                            sw.Flush();
                        }
                    }
                }
                catch (Exception ex)
                {
                    sw.Write("\r\n[" + DateTime.Now.ToString() + "] " + ex.Message + " Keyword: " + keyword +
                             " Questoin: " + i.ToString() + "\n\n\n");
                    sw.Flush();
                }

                QuestionParsed(this, new EventArgs());
                if (!_isContinue)
                    break;
            }
            sw.Close();
            return theDoc;
        }
    }

    internal struct question
    {
        private int _votes;

        public int votes
        {
            get { return _votes; }
        }

        private string _link;

        public string link
        {
            get { return _link; }
        }

        public question(int votes, string link)
        {
            this._votes = votes;
            this._link = link;
        }
    }
}